import type { App, Plugin } from 'vue'

// 把路径转换成驼峰命名
export const pathToCamel = (path: string): string => {
	return path.replace(/\/(\w)/g, (all, letter) => letter.toUpperCase())
}

// 是否外链
export const isExternalLink = (url: string): boolean => {
	return /^(https?:|\/\/|http?:|\/\/|^{{\s?apiUrl\s?}})/.test(url)
}

// 替换外链参数
export const replaceLinkParam = (url: string): string => {
	return url.replace('{{apiUrl}}', constant.apiUrl)
}

// 转换文件大小格式
export const convertSizeFormat = (size: number): string => {
	const unit = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB']
	let index = Math.floor(Math.log(size) / Math.log(1024))
	let newSize = size / Math.pow(1024, index)

	// 保留的小数位数
	return newSize.toFixed(2) + ' ' + unit[index]
}

// 获取svg图标(id)列表
export const getIconList = (): string[] => {
	const rs: string[] = []
	const list = document.querySelectorAll('svg symbol')
	for (let i = 0; i < list.length; i++) {
		rs.push(list[i].id)
	}
	return rs
}

// 获取字典Label
export const getDictLabel = (dictList: any[], dictType: string, dictValue: string) => {
	const type = dictList.find((element: any) => element.dictType === dictType)
	if (type) {
		const val = type.dataList.find((element: any) => element.dictValue === dictValue + '')
		if (val) {
			return val.dictLabel
		} else {
			return dictValue
		}
	} else {
		return dictValue
	}
}

// 获取字典数据列表
export function getDictDataList(dictList: any[], dictType: string) {
	const type = dictList.find((element: any) => element.dictType === dictType)
	if (type) {
		return type.dataList
	} else {
		return []
	}
}

// 获取项目名称
export const getValByProjectId = (projectList: any[], projectId: number) => {
	const project = projectList.find((element: any) => element.id === projectId)
	if (project) {
		const projectVal = project.name
		if (projectVal) {
			return projectVal
		} else {
			return projectId
		}
	} else {
		return projectId
	}
}

// 获取用户名称
export const getNameByUserId = (sysUserList: any[], userId: number) => {
	const user = sysUserList.find((element: any) => element.id === userId)
	if (user) {
		const username = user.username
		if (username) {
			return username
		} else {
			return userId
		}
	} else {
		return userId
	}
}

// 全局组件安装
export const withInstall = <T>(component: T, alias?: string) => {
	const comp = component as any
	comp.install = (app: App) => {
		app.component(comp.name || comp.displayName, component)
		if (alias) {
			app.config.globalProperties[alias] = component
		}
	}
	return component as T & Plugin
}
/**
 * 判断类型
 * @param {any}
 * @return {string}
 */
export function typeOf(argu) {
	const map = {
		'[object Number]': 'number',
		'[object String]': 'string',
		'[object Boolean]': 'boolean',
		'[object Undefined]': 'undefined',
		'[object Null]': 'null',
		'[object Array]': 'array',
		'[object Arguments]': 'arguments',
		'[object Function]': 'function',
		'[object Error]': 'error',
		'[object Date]': 'date',
		'[object RegExp]': 'regexp',
		'[object Object]': 'object'
	}
	const str = Object.prototype.toString.call(argu)
	return map[str]
}
/**
 * Parse the time to string
 * @returns number | string | array | object | null | undefined | boolean
 * @returns Boolean
 */
export function valuable(o: any): boolean {
	const type = typeOf(o)
	if (type === 'string' && o) {
		return true
	}
	if (type === 'number') {
		return true
	}
	if (type === 'array' && o.length) {
		return true
	}
	if (type === 'boolean') {
		return true
	}
	if (type === 'object' && Object.keys(o).length) {
		return true
	}
	return false
}
/**
 * Parse the time to string
 * @returns number | string | array | object | null | undefined | boolean
 * @returns Boolean
 */
export function valueReset<T>(o: T): T {
	const type = typeOf(o)
	if (type === 'string') {
		return ''
	} else if (type === 'number') {
		return 0
	} else if (type === 'array') {
		if (valuable(o)) {
			return o.map(v => {
				return valueReset(v)
			})
		} else {
			return []
		}
	} else if (type === 'object') {
		if (valuable(o)) {
			for (let key in o) {
				o[key] = valueReset(o[key])
			}
			return o
		} else {
			return {}
		}
	} else {
		return o
	}
}

// 转换时间格式
export const parseTime = (time: any, cFormat: string) => {
	// if (arguments.length === 0 || !time) {
	// 	return null
	// }
	if (!time) {
		return null
	}
	const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
	let date
	if (typeof time === 'object') {
		date = time
	} else {
		if (typeof time === 'string') {
			if (/^[0-9]+$/.test(time)) {
				// support "1548221490638"
				time = parseInt(time)
			} else {
				// support safari
				// https://stackoverflow.com/questions/4310953/invalid-date-in-safari
				time = time.replace(new RegExp(/-/gm), '/')
			}
		}

		if (typeof time === 'number' && time.toString().length === 10) {
			time = time * 1000
		}
		date = new Date(time)
	}
	const formatObj: any = {
		y: date.getFullYear(),
		m: date.getMonth() + 1,
		d: date.getDate(),
		h: date.getHours(),
		i: date.getMinutes(),
		s: date.getSeconds(),
		a: date.getDay()
	}
	const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
		const value = formatObj[key]
		// Note: getDay() returns 0 on Sunday
		if (key === 'a') {
			return ['日', '一', '二', '三', '四', '五', '六'][value]
		}
		return value.toString().padStart(2, '0')
	})
	return time_str
}
/**
 * 防抖
 * @param {funtion}
 * @param {number}
 * @return {undefined}
 */
export function debounce(fn, delay, _this) {
	var delay = delay || 200
	let timer = null
	return function () {
		const self = _this || this
		const args = arguments
		timer && clearTimeout(timer)
		timer = setTimeout(function () {
			timer = null
			fn.apply(self, args)
		}, delay)
	}
}
/**
 * 节流
 * @param {funtion}
 * @param {number}
 * @param {boolean} 是否间隔时间之后再执行
 * @return {undefined}
 */
export function throttle(fn, delay, path = false) {
	let last
	let timer
	const interval = delay || 200
	return function () {
		const self = this
		const args = arguments
		const now = +new Date()
		if (last && now - last < delay) {
			if (path) {
				clearTimeout(timer)
				timer = setTimeout(function () {
					last = now
					fn.apply(self, args)
				}, delay)
			}
		} else {
			last = now
			fn.apply(self, args)
		}
	}
}
type Item = {
	id: string
	pid: string
	name: string
	children?: Item[]
}
export function transMap(list: Item[]) {
	const childMap = new Map<string, Item[]>()
	const result: Array<Item> = []

	for (let i = 0; i < list.length; i++) {
		const item = list[i]
		if (item.pid) {
			const _children_ = childMap.get(item.pid) || []
			childMap.set(item.pid, _children_.concat(item))
		} else {
			result.push(item)
		}
	}

	function loop(list: Item[]) {
		list.map(v => {
			const children = childMap.get(v.id) || []

			if (children.length) {
				v.children = children
				loop(children)
			}

			return v
		})
	}

	loop(result)

	return result
}
